Handling Menu Choices
Your application is informed of user menu choices in a slightly roundabout fashion. First, your application receives a mouse-down event indicating that the user has clicked in the menu bar. At that time, you should call the Menu Manager functionMenuSelect
to determine which menu and menu item, if any, the user chose. When you callMenuSelect
, the Menu Manager pulls down the appropriate menu and tracks all subsequent mouse movement in the menu. When the user releases the mouse button,MenuSelect
exits and returns to your application a long integer that indicates which menu and item the user chose. The high-order word of that long integer contains the menu number, and the low-order word contains the menu item number.To coordinate the menu numbers and menu item numbers with the menus and menu items as defined in your
'MBAR'
and'MENU'
resources, you'll probably want to define a set of constants, as shown in Listing 8-2.Listing 8-2 Defining menu numbers and menu item numbers
CONST mApple = 128; {resource ID of Apple menu} iAbout = 1; {our About... dialog} mFile = 129; {resource ID of File menu} iNew = 1; iClose = 2; iQuit = 4; mEdit = 130; {resource ID of Edit menu} iUndo = 1; iCut = 3; iCopy = 4; iPaste = 5; iClear = 6; mVenn = 131; {resource ID of Venn menu} iCheckVenn = 1; iDoVenn = 2; iClearVenn = 3; iNextTask = 4; iCheckArg = 5; iGetVennPrefs = 7;In general, you'll define a routine like
- Note
- The divider in a menu counts as a menu item, even though the user can't choose it.
![]()
DoMenuCommand
shown in Listing 8-3 to handle all menu choices. Both your mouse-down event handler (Listing 6-9 on page 121) and your key-down event handler (Listing 8-5 on page 160) callMenuSelect
. It is passed either the result ofMenuSelect
(for menu selections) orMenuKey
(for keyboard equivalents of menu selections).Listing 8-3 Handling menu selections
PROCEDURE DoMenuCommand (menuAndItem: LongInt); VAR myMenuNum: Integer; myItemNum: Integer; myResult: Integer; myDAName: Str255; myWindow: WindowPtr; BEGIN myMenuNum := HiWord(menuAndItem); myItemNum := LoWord(menuAndItem); GetPort(myWindow); CASE myMenuNum OF mApple: CASE myItemNum OF iAbout: BEGIN DoAboutBox; END; OTHERWISE BEGIN GetMenuItemText(GetMenuHandle(mApple), myItemNum, myDAName); myResult := OpenDeskAcc(myDAName); END; END; mFile: BEGIN CASE myItemNum OF iNew: myWindow := DoCreateWindow; iClose: DoCloseWindow(FrontWindow); iQuit: DoQuit; OTHERWISE ; END; END; mEdit: BEGIN IF NOT SystemEdit(myItemNum - 1) THEN ; END; mVennD: BEGIN myWindow := FrontWindow; CASE myItemNum OF iCheckVenn: DoVennCheck(myWindow); iDoVenn: DoVennAnswer(myWindow); iClearVenn: DoVennClear(myWindow); iNextTask: DoVennNext(myWindow); iCheckArg: DoVennAssess(myWindow); iGetVennPrefs: DoModelessDialog(rVennDPrefsDial, gPrefsDialog); OTHERWISE ; END; END; OTHERWISE ; END; HiliteMenu(0); END;TheDoMenuCommand
procedure is passed a long integer that encodes the menu number and item number of the chosen item. As you can see,DoMenuCommand
consists mainly of aCASE
statement that branches on the menu number. Each menu number, in turn, consists mainly of aCASE
statement that branches on the menu item number. In this simple way, you can handle all menus and all menu items.Most of the innermost branches just call application-defined routines to handle the appropriate menu item choice. (For example, if the user chooses Quit from the File menu, then
DoMenuCommand
calls the application-defined routineDoQuit
.) The code that handles choices in the Apple menu (Listing 8-4) is slightly different, however.Listing 8-4 Handling Apple menu selections
iAbout: BEGIN DoAboutBox; END; OTHERWISE BEGIN GetMenuItemText(GetMenuHandle(mApple), myItemNum, myDAName); myResult := OpenDeskAcc(myDAName); END;If the user chooses the command About Venn Diagrammer (picked out by the constantiAbout
), thenDoMenuCommand
calls the application-defined routineDoAboutBox
(see Listing 7-7 on page 145). Otherwise, the user must have chosen a desk accessory or other item in the Apple menu. In that case,DoMenuCommand
retrieves the name of the desk accessory (by callingGetMenuItemText
) and passes that name to theOpenDeskAcc
function.Because Venn Diagrammer doesn't support any text editing, it simply calls the system software routine
SystemEdit
to handle user choices in the Edit menu.SystemEdit
checks whether the frontmost window belongs to a desk accessory; if so, it passes the menu choice to the desk accessory and returnsTRUE
. The parameter toSystemEdit
is interpreted so you can pass the item number less 1 of the standard Edit menu commands.Before exiting,
DoMenuCommand
calls the Menu Manager procedureHiliteMenu
to undo the menu title highlighting provided automatically byMenuSelect
orMenuKey
.